package com.opencee.cloud.base.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.opencee.cloud.base.constants.BaseApiType;
import com.opencee.cloud.base.constants.BaseGrantToType;
import com.opencee.cloud.base.constants.BaseResourceType;
import com.opencee.cloud.base.entity.BaseApiEntity;
import com.opencee.cloud.base.service.IBaseApiService;
import com.opencee.cloud.base.service.IBasePrivilegesService;
import com.opencee.cloud.base.vo.BaseApiVO;
import com.opencee.cloud.base.vo.BaseMenuVO;
import com.opencee.cloud.base.vo.params.BaseGrantParams;
import com.opencee.common.model.ApiResult;
import com.opencee.common.model.PageQuery;
import com.opencee.common.model.PageResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * API接口 前端控制器
 * </p>
 *
 * @author author
 * @since 2021-04-16
 */
@Api(tags = {"API接口"})
@RestController
@RequestMapping("/api")
public class BaseApiController {

    @Autowired
    private IBaseApiService apiService;
    @Autowired
    private IBasePrivilegesService privilegesService;


    @ApiOperation(value = "查询列表", notes = "查询列表")
    @GetMapping("/list")
    public ApiResult<List<BaseApiVO>> list(@RequestParam(value = "sid", required = false) String sid, @RequestParam(value = "type", required = false) String type, @RequestParam(value = "status", required = false) Integer status) {
        return ApiResult.ok().data(apiService.list(sid, status, BaseApiType.getByValue(type)));
    }

    /**
     * 分页查询
     *
     * @param pageQuery
     * @param entity
     * @return
     */
    @ApiOperation(value = "分页查询", notes = "分页查询")
    @GetMapping("/page")
    public ApiResult<PageResult<BaseApiVO>> page(PageQuery pageQuery, BaseApiEntity entity) {
        QueryWrapper<BaseApiEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .like(ObjectUtils.isNotEmpty(entity.getName()), BaseApiEntity::getName, entity.getName())
                .eq(ObjectUtils.isNotEmpty(entity.getSid()), BaseApiEntity::getSid, entity.getSid())
                .eq(ObjectUtils.isNotEmpty(entity.getParentId()), BaseApiEntity::getParentId, entity.getParentId())
                .eq(ObjectUtils.isNotEmpty(entity.getType()), BaseApiEntity::getType, entity.getType())
                .eq(ObjectUtils.isNotEmpty(entity.getStatus()), BaseApiEntity::getStatus, entity.getStatus());
        IPage<BaseApiEntity> page = apiService.page(pageQuery.buildIPage(), wrapper);
        Set<Long> parentIds = page.getRecords().stream().filter(t -> t.getParentId() != null).map(t -> t.getParentId()).collect(Collectors.toSet());
        Map<Long, BaseApiEntity> parentMap = apiService.mapByIds(parentIds);
        List<BaseApiVO> list = page.getRecords().stream().map(t -> {
            BaseApiVO vo = new BaseApiVO();
            BeanUtils.copyProperties(t, vo);
            BaseApiEntity parent = parentMap.get(t.getParentId());
            if (parent != null) {
                vo.setParentName(parent.getName());
            }
            return vo;
        }).collect(Collectors.toList());
        PageResult<BaseApiVO> result = new PageResult();
        result.setRecords(list);
        result.setTotal((int) page.getTotal());
        return ApiResult.ok().data(result);
    }

    @ApiOperation(value = "保存", notes = "保存")
    @PostMapping("/save")
    public ApiResult save(@RequestBody BaseApiVO vo) {
        if (vo.getId() == null) {
            apiService.save(vo);
        } else {
            apiService.update(vo);
        }
        return ApiResult.ok();
    }

    @ApiOperation(value = "删除", notes = "删除")
    @PostMapping("/remove")
    public ApiResult remove(@RequestParam("id") Long id) {
        apiService.removeById(id);
        return ApiResult.ok();
    }


    @ApiOperation(value = "批量删除", notes = "批量删除")
    @PostMapping("/removeByIds")
    public ApiResult removeByIds(@RequestParam("ids") Set<Long> ids) {
        apiService.removeByIds(ids);
        return ApiResult.ok();
    }

    @ApiOperation(value = "查询已授权列表", notes = "查询已授权列表")
    @PostMapping("/list/app-granted")
    public ApiResult<List<BaseMenuVO>> listGranted(@RequestParam("appId") Long appId) {
        return ApiResult.ok().data(privilegesService.listAppGrantedApi(appId, null));
    }

    @ApiOperation(value = "查询操作项关联接口列表", notes = "查询操作项关联接口列表")
    @PostMapping("/list/btn-granted")
    public ApiResult<List<BaseMenuVO>> listBtnGrantedApi(@RequestParam("btnId") Long btnId) {
        return ApiResult.ok().data(privilegesService.listBtnGrantedApi(btnId, null));
    }

    @ApiOperation(value = "保存授权", notes = "保存授权,覆盖原有权限")
    @PostMapping("/grant/save")
    public ApiResult grantSave(@Validated @RequestBody BaseGrantParams vo) {
        privilegesService.grantSave(BaseGrantToType.APP, BaseResourceType.API, vo);
        return ApiResult.ok();
    }

    @ApiOperation(value = "添加授权", notes = "添加授权,仅新增")
    @PostMapping("/grant/add")
    public ApiResult grantAdd(@Validated @RequestBody BaseGrantParams vo) {
        privilegesService.grantAdd(BaseGrantToType.APP, BaseResourceType.API, vo);
        return ApiResult.ok();
    }

    @ApiOperation(value = "移除授权", notes = "移除授权")
    @PostMapping("/grant/remove")
    public ApiResult grantRemove(@Validated @RequestBody BaseGrantParams vo) {
        privilegesService.grantRemove(BaseGrantToType.APP, BaseResourceType.API, vo);
        return ApiResult.ok();
    }

    @ApiOperation(value = "导入swagger文档", notes = "导入swagger文档")
    @PostMapping("/import/swagger")
    public ApiResult importSwagger(@RequestParam("sid") String sid, @RequestParam(value = "path", defaultValue = "/v2/api-docs") String path, @RequestParam(value = "basePath", defaultValue = "/") String basePath) {
        Integer count = apiService.importSwagger(sid, path, basePath);
        return ApiResult.ok("同步完成,共:" + count + "条");
    }


    @ApiOperation(value = "发布", notes = "发布接口")
    @PostMapping("/publish")
    public ApiResult publish(@RequestParam("ids") Set<Long> ids) {
        apiService.publish(ids);
        return ApiResult.ok();
    }

    @ApiOperation(value = "下线", notes = "下线接口")
    @PostMapping("/offline")
    public ApiResult offline(@RequestParam("ids") Set<Long> ids) {
        apiService.offline(ids);
        return ApiResult.ok();
    }

}
